#ifndef OPERATORIMPORTER_H
#define OPERATORIMPORTER_H

#define ZOOM 13//坐标和连接线长度缩放比例

#include <QObject>

#include <QFile>
#include <QtXml>
#include <QDebug>
#include <QDomElement>
#include <QDomDocument>

class QDomNode;
class QDomElement;
class QDomDocument;

//基础操作符中的参数,立即数或引用
struct parameter
{
    bool isImmediate=false;//是否为立即数
    QString value;
    QDomNode node;
};

//结构体变量的元素
typedef struct field
{
    QString name;
    QString type;
    QString oid;
}Field;

//数组变量的元素
typedef struct array
{
    QString type;
    parameter size;
}Array;

//变量
struct Variable
{
    QString id;          //变量id
    QString operatorId;  //操作符id
    QString name;        //变量名
    QString type;        //变量类型
    QString dataType;    //数据类型

    QDomNode node;//变量节点

    bool hasPara=false;//是否包含参数
    bool hasT=false;//是否包含泛型

    //default
    QDomNode defaultNode;
    QString defaultValue;

    //last
    QDomNode lastNode;
    QString lastValue;

    bool isLine=false;//是否为中间变量

    bool isStruct=false;
    bool isArray=false;

    QList<field> fieldList;
    Array array;


    QString comment;   //描述
    QString mnemonic;  //助记符
};

//结构体元素
struct label
{
    QString labelName;
    QString value;
};

//一元操作符
struct UnaryOp
{
    QString constVarRef;
};

//二元操作符
struct BinaryOp
{
    QStringList constVarRefs;
};

//多元操作符
struct NAryOp
{
    QStringList constVarRefs;
};

//Previous操作符
struct PreOp
{
    QStringList flows;
};

//Inin操作符
struct InitOp
{
    QList<parameter> parameters;
    QStringList flows;
};

//Followed By操作符
struct FbyOp
{
    QStringList flows;
    parameter delay;
    QList<parameter> parameters;
};

//Projection操作符
struct PrjOp
{
    QString flow;
    QList<parameter> parameters;
};

//Slice操作符
struct SliceOp
{
    QString array;//输入
    parameter fromIndex;
    parameter toIndex;
};

//Dynamic Projection操作符
struct PrjDynOp
{
    QString array;//输入
    QList<parameter> indexes;
    parameter defaultpara;
};

//DataStructure操作符
struct DataStructOp
{
    QList<label> labels;
};

//ScalarToVector
struct ScalarToVectorOp
{
    QStringList flows;
    parameter size;
};

//DataArray
struct DataArrayOp
{
    QStringList datas;
};

//Assign of a Structrued Element
struct ChgIthOp
{
    QString flow;
    QList<parameter> parameters;
    QString value;
};

//If Then Else
struct IfThenElseOp
{
    QString ifValue;
    QStringList thens;
    QStringList elses;
};

//Case
struct CaseOp
{
    QString switchValue;
    QList<label> cases;
    QString defaultValue;
};

//Make
struct MakeOp
{
    QString typeRef;
    QStringList calls;
};

//Flatten
struct FlattenOp
{
    QString typeRef;
    QString call;
};

//Iterator
struct IteratorOp
{
    QString iteratorType;//高阶类型
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符
    parameter size;
    QStringList calls;//输入

    QString usedIdName;
    QString refName;
};

//PartialIterator
struct PartialIteratorOp
{
    QString partialIteratorType;//高阶类型
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符
    parameter size;
    QString ifValue;
    bool hasDefault=false;
    parameter defaultValue;
    QStringList calls;//输入

    QString usedIdName;
    QString refName;
};

//用户自定义操作符
struct OpCall
{
    QString operatorRef;
    QStringList calls;
};

struct LineLength
{
    int hLength;
    int zLength;
};

struct Line
{
    QString leftIndex;
    QString rightIndex;

    QString leftEquationOid;
    QString rightEquationOid;

    int beginX;//连接线起点坐标
    int beginY;

    int endX;//连接线终点坐标
    int endY;
    int id;//图元ID
    QList<LineLength> lineLengthList;
};


//端口坐标
struct portCoordinate
{
    QString type;//端口类型
    QString paraValue;//当端口为参数端口，且参数为立即数时的值
    Line linkLine;//if、in、para端口的连接线
    int x;
    int y;
};

//被调用的含参数的操作符
struct opcallParaOperator
{
    parameter paraValue;//参数值
    QString operatorName;//操作符名
};

//逻辑里的图元
struct Equation
{
    QDomNode node;//等式节点

    QString oid;//图元oid
    QString redaceId;//生成的REDACEoid
    QString pageId;//图元所在图形页id

    QString type;//图元类型
    QString name;//图元名字
    QString comment;//图元注释

    QStringList lefts;//左值
    QString rightVarRef;//图元为变量或常量时的右值

    QString operatorType;//操作符种类
    QString operatorName;//操作符名字

    int id;//图元EleID

    QString opeName;
    QString eleType;
    QString text;

    QList<portCoordinate> ifList;//if端口
    QList<portCoordinate> inList;//输入端口
    QList<portCoordinate> paraList;//参数端口
    QList<portCoordinate> outList;//输出端口

    QList<portCoordinate> rightList;//if、out、para列表
//    QString ifNum;
//    QString inNum;
//    QString ParaNum;
//    QString outNum;

    int x;
    int y;
    int width;
    int height;

//    int linkId=10000;

    UnaryOp unaryOp;
    BinaryOp binaryOp;
    NAryOp nAryOp;
    PreOp preOp;
    InitOp initOp;
    FbyOp fbyOp;
    PrjOp prjOp;
    SliceOp sliceOp;
    PrjDynOp prjDynOp;
    DataStructOp dataStructOp;
    ScalarToVectorOp scalarToVectorOp;
    DataArrayOp dataArrayOp;
    ChgIthOp chgIthOp;
    IfThenElseOp ifThenElseOp;
    CaseOp caseOp;
    MakeOp makeOp;
    FlattenOp flattenOp;
    IteratorOp iteratorOp;
    PartialIteratorOp partialIteratorOp;
    OpCall opCall;

    bool isLastVar=false;//是否为last变量

    bool isParaHigh=false;//是否为使用了参数的高阶操作符
    parameter paraValue;//参数的实例化的值

    bool isUnsupport=false;//是否为REDACE不支持的操作符


};

//图形页面
struct Diagram
{
    QString name;//名字
    QString oid;//oid
    QString redaceOid;//REDACEoid
    QString landscape;//landsacpe

    QList<Equation> equations;//图元
    QList<Line> lineList;//连接线

};

//被调用的含泛型操作符
struct opcallOperator
{
    Equation equation;
    QString operatorName;//操作符名
    QString opcallName;//被调用的操作符名
};

//操作符
struct OperatorData
{
    QString operatorName;
    QString path;
    QString operatorFileName;

    bool isImported=false;//是否是导入操作符
    bool hasPara=false;//是否包含参数
    bool hasT=false;//是否包含泛型
    QString cFilePath;

    QString oid;//操作符oid
    QString comment;//操作符注释
    QString kind;//种类

    QString parameter;//参数

    bool isNew=false;//是否为参数实例化的操作符

    QList<opcallParaOperator> paraOperatorList;//操作符中调用的含参自定义操作符

    QList<opcallOperator> opCallList;//操作符中调用的自定义操作符

    QList<Variable> variables;//变量

    QList<Equation> equations;//逻辑

    QList<Diagram> diagrams;//页面

    QStringList logList;//导入日志
};

class OperatorImporter : public QObject
{
    Q_OBJECT
public:
    explicit OperatorImporter(QObject *parent = nullptr);

    bool readOperatorFile(const QDomNode &root);

    void dataProcess(QFile &file,OperatorData &datas);

    void saveOperatorFile(const QString &redaceProjectPath,const QString &scadeProjectName,const QString &operatorFileName,OperatorData &datas);

    void saveDiagramFile(const QString &filePath,OperatorData &datas);

    void dataProcess_64(OperatorData &datas,QDomDocument &doc);

    void saveOperatorFile_64(const QString &redaceProjectPath,const QString &scadeProjectName,const QString &operatorFileName,OperatorData &datas);

    parameter parseParameter(const QDomElement &element);

private:
    void correctionOperatorFile(QFile &file);

    void parseVariables(const QDomElement &element);

    void parseNomalVariable(Variable &data,const QDomElement &element);

    void parseStructVariable(Variable &data,const QDomElement &element);

    void parseArrayVariable(Variable &data,const QDomElement &element);

    void parseDatas(const QDomElement &element);

    void parseBaseOperator(const QDomElement &element,Equation &data);

    void parseUnaryOp(const QDomElement &element,Equation &data);

    void parseBinaryOp(const QDomElement &element,Equation &data);

    void parseNAryOp(const QDomElement &element,Equation &data);

    void parsePreOp(const QDomElement &element,Equation &data);

    void parseInitOp(const QDomElement &element,Equation &data);

    void parseFbyOp(const QDomElement &element,Equation &data);

    void parsePrjOp(const QDomElement &element,Equation &data);

    void parseSliceOp(const QDomElement &element,Equation &data);

    void parsePrjDynOp(const QDomElement &element,Equation &data);

    void parseDataStructOp(const QDomElement &element,Equation &data);

    void parseScalarToVectorOp(const QDomElement &element,Equation &data);

    void parseDataArrayOp(const QDomElement &element,Equation &data);

    void parseChgIthOp(const QDomElement &element,Equation &data);

    void parseIfThenElseOp(const QDomElement &element,Equation &data);

    void parseCaseOp(const QDomElement &element,Equation &data);

    void parseMakeOp(const QDomElement &element,Equation &data);

    void parseFlattenOp(const QDomElement &element,Equation &data);

    void parseIteratorOp(const QDomElement &element,Equation &data);

    void parsePartialIteratorOp(const QDomElement &element,Equation &data);

    void parseOpCall(const QDomElement &element,Equation &data);

    void parsePragmas(const QDomElement &element);

    void parseDiagram(const QDomElement &element);

    void diagramProcess(OperatorData &datas);

    void saveVariable(QXmlStreamWriter &writer,const Variable &data);

    void saveEquation(QXmlStreamWriter &writer,const Equation &data);

    void saveOperator(QXmlStreamWriter &writer,const Equation &data);

    void saveUnaryOp(QXmlStreamWriter &writer,const Equation &data);

    void saveBinaryOp(QXmlStreamWriter &writer,const Equation &data);

    void saveNAryOp(QXmlStreamWriter &writer,const Equation &data);

    void savePreOp(QXmlStreamWriter &writer,const Equation &data);

    void saveInitOp(QXmlStreamWriter &writer,const Equation &data);

    void saveFbyOp(QXmlStreamWriter &writer,const Equation &data);

    void savePrjOp(QXmlStreamWriter &writer,const Equation &data);

    void saveSliceOp(QXmlStreamWriter &writer,const Equation &data);

    void savePrjDynOp(QXmlStreamWriter &writer,const Equation &data);

    void saveDataStructOp(QXmlStreamWriter &writer,const Equation &data);

    void saveScalarToVectorOp(QXmlStreamWriter &writer,const Equation &data);

    void saveDataArrayOp(QXmlStreamWriter &writer,const Equation &data);

    void saveChgIthOp(QXmlStreamWriter &writer,const Equation &data);

    void saveIfThenElseOp(QXmlStreamWriter &writer,const Equation &data);

    void saveCaseOp(QXmlStreamWriter &writer,const Equation &data);

    void saveMakeOp(QXmlStreamWriter &writer,const Equation &data);

    void saveFlattenOp(QXmlStreamWriter &writer,const Equation &data);

    void saveIteratorOp(QXmlStreamWriter &writer,const Equation &data);

    void savePartialIteratorOp(QXmlStreamWriter &writer,const Equation &data);

    void saveOpCall(QXmlStreamWriter &writer,const Equation &data);

    void saveIdExpression(QXmlStreamWriter &writer,const QString &data);

    void saveParameter(QXmlStreamWriter &writer,const parameter &data);

    void saveEquationGE(QXmlStreamWriter &writer,const int &i,OperatorData &datas,int &eleIDindex,int &outPortIndex);

    void saveLineGE(QXmlStreamWriter &writer,const int &i,OperatorData &datas,int &eleIDindex);

    void parseEquationPorts(Equation &data);

    void parseUnaryOpPorts(Equation &data);

    void parseBinaryOpPorts(Equation &data);

    void parseNAryOpPorts(Equation &data);

    void parsePreOpPorts(Equation &data);

    void parseInitOpPorts(Equation &data);

    void parseFbyOpPorts(Equation &data);

    void parsePrjOpPorts(Equation &data);

    void parseSliceOpPorts(Equation &data);

    void parsePrjDynOpPorts(Equation &data);

    void parseDataStructOpPorts(Equation &data);

    void parseScalarToVectorOpPorts(Equation &data);

    void parseDataArrayOpPorts(Equation &data);

    void parseChgIthOpPorts(Equation &data);

    void parseIfThenElseOpPorts(Equation &data);

    void parseCaseOpPorts(Equation &data);

    void parseMakeOpPorts(Equation &data);

    void parseFlattenOpPorts(Equation &data);

    void parseIteratorOpPorts(Equation &data);

    void parsePartialIteratorOpPorts(Equation &data);

    void parseOpCallPorts(Equation &data);

    QString parseIdExpression(const QDomElement &element);   

    QString getOid(const QDomNode &idNode);

    QString getComment(const QDomNode &commentNode);

    QString judgeVarType(QString &varName);

public:
    OperatorData m_operator;

};

#endif // OPERATORIMPORTER_H
